package com.baoyouqun.API.wxPay;

import com.baoyouqun.service.OrderRecordService;
import com.wechat.pay.java.core.RSAPublicKeyConfig;
import com.wechat.pay.java.core.exception.HttpException;
import com.wechat.pay.java.core.exception.MalformedMessageException;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.model.Transaction;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

/**
 * 微信支付服务实现（完全适配JsapiService源码）
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class WechatPayServiceImpl implements WechatPayService {

    // 注入配置和核心服务（从WxPayConfig中获取）
    private final WxPayConfig wxPayConfig;
    private final JsapiServiceExtension jsapiServiceExtension;
    private final RSAPublicKeyConfig rsaConfig;
    private final NotificationConfig notificationConfig;

    @Resource
    private OrderRecordService orderRecordService;

    /**
     * 创建JSAPI预支付订单（核心方法，适配JsapiServiceExtension源码）
     */
    @Override
    public PrepayWithRequestPaymentResponse createJsapiPayOrder(String orderId, String payName, BigDecimal price, String openid) {
        try {
            // 1. 构建预支付请求对象（PrepayRequest，源码要求的参数）
            PrepayRequest prepayRequest = new PrepayRequest();
            prepayRequest.setAppid(wxPayConfig.getAppid());          // 小程序appid
            prepayRequest.setMchid(wxPayConfig.getMchid());          // 商户号
            prepayRequest.setDescription(payName);                   // 商品描述
            prepayRequest.setOutTradeNo(orderId);                    // 商户订单号
            prepayRequest.setNotifyUrl(wxPayConfig.getNotifyUrl());  // 支付结果通知地址

            // 新增：初始化amount对象
            prepayRequest.setAmount(new Amount());
            // 设置支付金额（微信要求单位：分，需转换）
            prepayRequest.getAmount().setTotal(price.multiply(new BigDecimal(100)).intValue());
            Payer payer = new Payer();
            payer.setOpenid(openid);
            prepayRequest.setPayer(payer);

            // 2. 调用源码方法获取调起支付参数（无getPrepayId()，直接返回封装好的响应）
            return jsapiServiceExtension.prepayWithRequestPayment(prepayRequest);

        } catch (HttpException e) {
            log.error("创建预支付订单：HTTP请求失败（如网络错误）", e);
            throw new RuntimeException("支付请求发送失败，请检查网络");
        } catch (ServiceException e) {
            log.error("创建预支付订单：微信服务返回错误（错误码：{}）", e.getErrorCode(), e);
            throw new RuntimeException("支付服务异常：" + e.getErrorMessage());
        } catch (MalformedMessageException e) {
            log.error("创建预支付订单：响应解析失败", e);
            throw new RuntimeException("支付参数解析异常");
        }
    }

    /**
     * 处理微信支付通知（适配源码的通知解析逻辑）
     */
    @Override
    public String handlePayNotify(String notifyData, String serial, String signature, String nonce, String timestamp) {
        try {
            // 1. 关键修正：严格按照源码的Builder模式创建RequestParam
            RequestParam requestParam = new RequestParam.Builder()
                    .serialNumber(serial)    // 设置微信支付证书序列号（对应请求头Wechatpay-Serial）
                    .timestamp(timestamp)    // 设置时间戳（对应请求头Wechatpay-Timestamp）
                    .nonce(nonce)            // 设置随机字符串（对应请求头Wechatpay-Nonce）
                    .signature(signature)    // 设置签名（对应请求头Wechatpay-Signature）
                    .body(notifyData)        // 设置通知内容（请求体）
                    .build();                // 生成RequestParam实例

            // 2. 解析通知为Transaction对象（微信支付订单信息）
            NotificationParser parser = new NotificationParser(notificationConfig); // 传入配置实例
            Transaction transaction = parser.parse(requestParam, Transaction.class); // 调用实例方法


            // 3. 业务逻辑：更新商户订单状态（需替换为你的实际业务）
            String outTradeNo = transaction.getOutTradeNo(); // 商户订单号

            Transaction.TradeStateEnum tradeState = transaction.getTradeState(); // 支付状态（SUCCESS/NOT_PAY等）
            if (Transaction.TradeStateEnum.SUCCESS.equals(tradeState)) {
                log.info("订单支付成功：商户订单号={}，微信订单号={}", outTradeNo, transaction.getTransactionId());
                // TODO：调用你的订单服务更新状态（需保证幂等性）
                orderRecordService.updateInvoiceStatus(outTradeNo, (byte) 1);
            } else {
                log.warn("订单支付状态异常：商户订单号={}，状态={}", outTradeNo, tradeState);
            }

            // 4. 返回微信要求的成功响应（XML格式）
            return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";

        } catch (Exception e) {
            log.error("处理支付通知失败", e);
            // 处理失败返回FAIL，微信会重试
            return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[处理失败]]></return_msg></xml>";
        }
    }

    /**
     * 查询订单状态（根据商户订单号，适配JsapiService源码）
     */
    @Override
    public Transaction queryOrderByOutTradeNo(String orderId) {
        try {
            // 构建查询请求对象（QueryOrderByOutTradeNoRequest，源码要求）
            QueryOrderByOutTradeNoRequest queryRequest = new QueryOrderByOutTradeNoRequest();
            queryRequest.setOutTradeNo(orderId);          // 商户订单号
            queryRequest.setMchid(wxPayConfig.getMchid());// 商户号

            // 调用源码的查询方法
            return jsapiServiceExtension.queryOrderByOutTradeNo(queryRequest);

        } catch (ServiceException e) {
            log.error("查询订单：微信服务返回错误（订单号：{}，错误码：{}）", orderId, e.getErrorCode(), e);
            throw new RuntimeException("查询支付状态失败：" + e.getErrorMessage());
        } catch (Exception e) {
            log.error("查询订单失败（订单号：{}）", orderId, e);
            throw new RuntimeException("查询支付状态异常");
        }
    }

    /**
     * 关闭未支付订单（适配JsapiService源码）
     */
    @Override
    public void closeOrder(String orderId) {
        try {
            // 构建关闭订单请求对象（CloseOrderRequest，源码要求）
            CloseOrderRequest closeRequest = new CloseOrderRequest();
            closeRequest.setOutTradeNo(orderId);          // 商户订单号
            closeRequest.setMchid(wxPayConfig.getMchid());// 商户号

            // 调用源码的关闭方法（无返回值，成功即无异常）
            jsapiServiceExtension.closeOrder(closeRequest);
            log.info("订单关闭成功：商户订单号={}", orderId);

        } catch (ServiceException e) {
            log.error("关闭订单：微信服务返回错误（订单号：{}，错误码：{}）", orderId, e.getErrorCode(), e);
            throw new RuntimeException("关闭订单失败：" + e.getErrorMessage());
        } catch (Exception e) {
            log.error("关闭订单失败（订单号：{}）", orderId, e);
            throw new RuntimeException("关闭订单异常");
        }
    }
}